package com.cory.utils.security;

/**
 * 字节数组简单加密、解密
 * 
 * @author xc
 * @version 2016-12-12
 */
public class ByteCoder {
	
	    /**
     * 字节数组移位 step移动多少位，正数右移，负数左移
     */
	public static byte[] move(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % len;
		if (step == 0) return data;
		
		byte[] ret = new byte[len];
		if (step > 0) {
			for (int i = 0; i < ret.length; i++) {
				ret[i] = data[( i - step + len) % len];
			}
			return ret;
		} else if(step < 0) {
			step = -step;
			for (int i = 0; i < ret.length; i++) {
				ret[i] = data[( i + step ) % len];
			}
			return ret;
		}
			
		return data;
	}
	
	    /**
     * 字节数组交换 每个字节都和他距离step的字节交换
     */
	public static byte[] exchange(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % len;
		if (step <= 0) return data;
		
		for (int i = 0; i < len ; i = (i + step * 2)) {
			for (int j = 0; j < step; j ++) {
				if (i + j + step < len) {
					byte tmp = data[i + j];
					data[i + j] = data[i + j + step];
					data[i + j + step] = tmp;
				} 
			}
		}
		
		return data;
	}
	
	    /**
     * 字节数组异或运算 每个字节都和他距离step的字节为一对做异或运算 前一个字节被异或结果替换，后一个不变
     */
	public static byte[] xor(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % len;
		if (step <= 0) return data;
		
		for (int i = 0; i < len ; i = (i + step * 2)) {
			for (int j = 0; j < step; j ++) {
				if (i + j + step < len) {
					data[i + j] = (byte)(data[i + j] & 0xFF ^ data[i + j + step] & 0xFF);
				} 
			}
		}
		
		return data;
	}
	
	    /**
     * 字节数组异或运算 每个字符都和tmp做异或运算，并被异或结果替换
     */
	public static byte[] xor(byte[] data, byte tmp) {
		if (data == null || data.length == 0) return data;
		
		for (int i = 0; i < data.length ; i++) {
			data[i] = (byte)(data[i] & 0xFF ^ tmp & 0xFF);
		}
		
		return data;
	}
	
	    /**
     * 字节数组异或运算 数组以tmp数组长度为一组，和tmp进行对应位置字节做异或运算，并被异或结果替换
     */
	public static byte[] xor(byte[] data, byte[] tmp) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		int tlen = tmp.length;
		
		for (int i = 0; i < len ; i = (i + tlen)) {
			for (int j = 0; j < tlen; j++) {
				if (i + j < len) {
					data[i + j] = (byte)(data[i + j] & 0xFF ^ tmp[j] & 0xFF);
				} 
			}
		}
		
		return data;
	}
	
	    /**
     * 字节数组二进制移位 每个字节转为二进制，向一侧移动，移出部分加在另一侧头部 step移动多少位，正数右移，负数左移
     */
	public static byte[] binary(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % 8;
		if (step == 0) return data;
		
		for (int i = 0; i < len; i++) {
			String binary = Integer.toBinaryString((data[i] & 0xff) + 0x100).substring(1);
			
			int blen = binary.length();
			if (step > 0) {
				binary = binary.substring(blen - step).concat(binary.substring(0, blen - step));
			} else if (step < 0) {
				binary = binary.substring(-step).concat(binary.substring(0, -step));
			}
			
			if (binary.startsWith("1")) {
				binary = binary.replaceAll("1", "e").replaceAll("0", "1").replaceAll("e", "0");

				byte[] bytes = binary.getBytes();
				for (int j = binary.length() - 1; j >= 0; j--) {
					if (bytes[j] == 48) {
						bytes[j] = 49;
						break;
					} else {
						bytes[j] = 48;
					}
				}
				
				binary = new String(bytes);
				data[i] = (byte)(-Integer.parseInt(binary, 2));
			} else {
				data[i] = Byte.parseByte(binary, 2);
			}
		}
		
		return data;
	}
	
	    /**
     * 字节数组十六进制换位 每个字节转为十六进制，并将2位十六进制数交换
     */
	public static byte[] hex(byte[] data) {
		if (data == null || data.length == 0) return data;
		
		for (int i = 0; i < data.length; i++) {
			String hex = Integer.toHexString((data[i] & 0xff) + 0x100).substring(1);
			
			hex = hex.toUpperCase();
			hex = hex.charAt(1) + "" + hex.charAt(0);
			
			String code = "0123456789ABCDEF";
			data[i] = (byte)(code.indexOf(hex.charAt(0)) << 4 | code.indexOf(hex.charAt(1)));
		}
		
		return data;
	}
	
	    /**
     * 字节数组十六进制移位 整个字节数组转为十六进制，向一侧移动，移出部分加在另一侧头部 step移动多少位，正数右移，负数左移 step应为奇数，偶数等同于move(data,
     * step/2)
     */
	public static byte[] hex(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % (len * 2);
		if (step == 0) return data;
		
		StringBuffer hex = new StringBuffer();
		for (int i = 0; i < len; i++) {
			hex.append(Integer.toHexString((data[i] & 0xff) + 0x100).substring(1));
		}
		
		int hlen = hex.length();
		if (step > 0) {
			hex = new StringBuffer(hex.substring(hlen - step).concat(hex.substring(0, hlen - step)));
		} else if (step < 0) {
			hex = new StringBuffer(hex.substring(-step).concat(hex.substring(0, -step)));
		}
		
		String code = "0123456789ABCDEF";
		byte[] tmp = hex.toString().toUpperCase().getBytes();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			data[i] = (byte)(code.indexOf(tmp[pos]) << 4 | code.indexOf(tmp[pos + 1]));
		}
		
		return data;
	}
	
	    /**
     * 字节数组四进制移位 整个字节数组转为四进制，向一侧移动，移出部分加在另一侧头部 step移动多少位，正数右移，负数左移 step不应为4的倍数，4的倍数等同于move(data,
     * step/4)
     */
	public static byte[] base4(byte[] data, int step) {
		if (data == null || data.length == 0) return data;
		
		int len = data.length;
		step = step % (len * 4);
		if (step == 0) return data;
		
		StringBuffer base4 = new StringBuffer();
		for (int i = 0; i < len; i++) {
			base4.append(Integer.toString((data[i] & 0xff) + 0x100, 4).substring(1));
		}
		
		int blen = base4.length();
		if (step > 0) {
			base4 = new StringBuffer(base4.substring(blen - step).concat(base4.substring(0, blen - step)));
		} else if (step < 0) {
			base4 = new StringBuffer(base4.substring(-step).concat(base4.substring(0, -step)));
		}
		
		String code = "0123";
		byte[] tmp = base4.toString().getBytes();
		for (int i = 0; i < len; i++) {
			int pos = i * 4;
			data[i] = (byte)(code.indexOf(tmp[pos]) << 6 | code.indexOf(tmp[pos + 1]) << 4 
					| code.indexOf(tmp[pos + 2]) << 2 | code.indexOf(tmp[pos + 3]));
		}
		
		return data;
	}
	
}
